package cn.bigcontainer.alt.meta.po;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.bigcontainer.alt.common.util.WoJsonKit;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.annotation.JsonIgnore;

import cn.bigcontainer.alt.common.entity.BigMap;
import cn.bigcontainer.alt.common.util.WoKit;
import cn.bigcontainer.alt.common.util.WoVelocityKit;
import cn.bigcontainer.alt.meta.dto.MAppDto;
import cn.bigcontainer.alt.meta.dto.MCrud;
import cn.bigcontainer.alt.meta.dto.MObjectDto;
import cn.bigcontainer.alt.meta.dto.MViewDto;
import cn.bigcontainer.alt.meta.exception.MException;
import cn.bigcontainer.alt.meta.mapper.MAppMapper;
import lombok.extern.slf4j.Slf4j;

/**
 * 视图属性，不会存在单独的表中，作为json保存在cn.bigcontainer.alt.meta.po.MView#mViewProperties中
 *
 * @author cailei
 * @date 2019-12-04
 */
@Slf4j
public class MViewProperty implements Comparable<MViewProperty> {

    /**
     * 升序
     */
    public final static String ORDER_ASC = "ASC";

    /**
     * 降序
     */
    public final static String ORDER_DESC = "DESC";

    public final static String PARAM_ORDER_INDEX = "orderIndex";

    public final static String PARAM_ORDER_TYPE = "orderType";

    /**
     * 隐藏
     */
    public final static String TYPE_HIDDEN = "hidden";

    /**
     * 文本
     */
    public final static String TYPE_TEXT = "textfield";

    /**
     * 数据字典
     */
    public final static String TYPE_DICTIONARY = "dictionary";

    /**
     * 图标
     */
    public final static String TYPE_ICON = "icon";

    /**
     * 附件
     */
    public final static String TYPE_FILE = "file";
    
    /**
     * 图片
     */
    public final static String TYPE_IMAGE = "image";

    public final static String TYPE_NUMBER = "numberfield";
    public final static String TYPE_OBJECT_SELECTOR = "objectSelector";
    public final static String TYPE_OBJECT_INPUTOR = "objectInputor";
    public final static String TYPE_OBJECT12M = "object12m";
    public final static String TYPE_DATETIME = "datetime";
    public final static String TYPE_DATE = "date";
    public final static String TYPE_TEXTAREA = "textarea";
    public final static String TYPE_COMBO = "combo";
    public final static String TYPE_CHECK = "checkbox";
    public final static String TYPE_RADIO = "radio";
    public final static String TYPE_COMBOM21 = "comboM21";
    public final static String TYPE_ORGSEARCH = "orgSearch";
    public final static String TYPE_FIELDSET = "fieldset";

    public final static String SUFFIX_NAME = "__NAMEVALUE";

    public final static String SUFFIX_FILEHIDDEN = "__WOFILEHIDDEN";

    public final static String SUFFIX_SELECTORHIDDEN = "__WOSELECTORHIDDEN";

    /**
     * 对于用户输入值或者数据库读取值，为空时替换为W_INITVALUE或者W_SUBMITVALUE
     */
    public final static int REPLACE_EMPTY = 1;
    /**
     * 对于用户输入值或者数据库读取值，不为空时替换为W_INITVALUE或者W_SUBMITVALUE
     */
    public final static int REPLACE_VALUE = 2;

    /**
     * data中的值参数
     */
    public final static String PARAM_VALUE = "value";

    /**
     * woData中的关联对象名称属性值参数，对应的值为Object[]
     */
    public final static String PARAM_NAME_VALUE = "nameValue";

    /**
     * 视图属性中参数，小数位数
     */
    public final static String PARAM_SCALE = "numberScale";

    /**
     * 视图(type=form)属性中参数，表示视图加载时，是否用W_INITVALUE替换从数据库中读取的值
     */
    public final static String PARAM_REPLACE_INIT = "replaceInit";

    /**
     * 视图(type=form)属性中参数，表示视图提交时，是否用W_SUBMITVALUE替换用户输入的值value。0-表示不替换，1-表示仅value为空时替换，2-
     * 表示无条件替换
     */
    public final static String PARAM_REPLACE_SUBMIT = "replaceSubmit";
    /**
     * 特殊属性中参数，表示关联的crud
     */
    public final static String PARAM_RELATED_CRUD = "relatedCrud";

    /**
     * 特殊属性中参数，false表示多选，否则单选，objectInputor/objectSelector等控件需要配置该参数
     */
    public final static String PARAM_RELATED_SINGLE = "relatedSelectorSingle";

    /**
     * objectInputor参数，当用户输入内容后，根据内容查询数据url
     */
    public final static String PARAM_SEARCH_URL = "searchUrl";
    
    /**
     * objectInputor参数，根据id值，获取名称数据用于显示
     */
    public final static String PARAM_DATA_URL = "dataUrl";
    
    /**
     * data中参数，控件为checkboxfilter时，需要填写
     */
    public final static String PARAM_LIST_FILTER = "listFilter";
    
    /**
     * data中参数，有值表示该属性从前端ajax获取数据的url，否则表示后端获取
     */
    public final static String PARAM_AJAX = "ajax";
    
    /**
     * data中参数，当ajax的url为meta/listproperty/sql时，需要填写该值
     */
    public final static String PARAM_AJAX_SQL = "ajaxSql";
    
    /**
     * data中参数，当列表视图的控件为expression时，需要填充
     */
    public final static String PARAM_EXPRESSION = "expression";
    
    /**
     * 特殊属性中参数，表示对象选择器选择个数限制
     */
    // public final static String PARAM_SELECTED_LEN = WO_APPS.PARAM_SELECTED_LEN;
    /**
     * 特殊属性中参数，其值对应数据字典的类型
     */
	public final static String PARAM_DICTIONARY = "dictionaryType";

    /**
     * 控件类型为objectListor/objectSelector时，需要设置被关联crud需要传入的参数字段
     */
    public final static String PARAM_LISTOR_FIELD = "listorField";

    /**
     * 配合PARAM_LISTOR_FIELD参数使用的，如果不设置该参数，则使用主键值，否则根据该参数通过后缀查找视图属性获得值
     */
    public final static String PARAM_LISTOR_SUFFIX = "listorSuffix";

    /**
     * 特殊属性中参数，其值对为COMPARE_LIKE/COMPARE_EQUAL等
     */
    public final static String PARAM_COMPARE = "compareType";

    /**
     * 特殊属性中参数，PARAM_COMPARE = COMPARE_EXPRESSION时，需要设置表达式，例如：{"searchExpression" : "like '${value}%'"}
     */
    public final static String PARAM_COMPARE_EXP = "searchExpression";

    /**
     * 如果W_PROPS_ID和W_RELATIONS_ID都没有配置，可以在W_SPROPS配置json数据，例如：{"woSearchProps"
     * : "WO_APPS_M_ID,WO_APPS_M_NAME"}.WO_APPS_M_ID等属性必须是本方对象的.
     */
    public final static String COMPARE_LIKE = "like";
    /**
     * 如果W_PROPS_ID和W_RELATIONS_ID都没有配置，可以在W_SPROPS配置json数据，例如：{"woSearchProps"
     * : "WO_APPS_M_ID,WO_APPS_M_NAME"}.
     */
    public final static String COMPARE_EQUAL = "equal";
    /**
     * 需要在W_SPROPS配置json数据，例如：{"searchExpression" : "like '${value}%'"}.
     */
    public final static String COMPARE_EXPRESSION = "expression";
    /**
     * 多表达式：表达式从UI选择后传入后台，例如，该视图属性对应一个下拉框，对应多个表达式，用户选择后提交到后台
     */
    public final static String COMPARE_SELECT_EXPRESSION = "select-expression";

    protected String id;

    protected Integer index;

    protected String name;

    protected String type;

    protected String propertyId;

    protected String relationId;

    protected Integer width;

    protected Integer height;

    protected String initValue;

    protected String submitValue;

    protected Integer submit;

    protected Integer rowSpan;

    protected Integer colSpan;

    protected String min;

    protected String max;

    protected Integer allowsBlank;

    protected Integer unique;

    protected Integer readonly;

    /**
     * 特殊属性数据
     */
    protected BigMap<String, Object> data = new BigMap<>();

    /**
     * 内存数据，不需要序列化
     */
    @JsonIgnore
    private MViewDto view;

    public MViewProperty setValue(Object value) {
        data.put(PARAM_VALUE, value);
        return this;
    }

    @JsonIgnore
    public Object getValue () {
        return data.get(PARAM_VALUE);
    }

    @JsonIgnore
    public Integer getOrderIndex() {
        return data.getInt(PARAM_ORDER_INDEX, -1);
    }

    public void setOrderIndex (Integer orderIndex) {
        data.put(PARAM_ORDER_INDEX, orderIndex);
    }

    @JsonIgnore
    public String getOrderType() {
        return data.getString(PARAM_ORDER_TYPE, ORDER_ASC);
    }

    public void setOrderTypeDesc () {
        setOrderType(ORDER_DESC);
    }

    public void setOrderType (String orderType) {
        data.put(PARAM_ORDER_TYPE, orderType);
    }
    
    public void toggleOrderType () {
    	if (ORDER_DESC.equals(getOrderType())) {
    		setOrderType(ORDER_ASC);
    	} else {
    		setOrderType(ORDER_DESC);
    	}
    }

    /**
     * 获取本方或者关联对象属性
     * @return
     */
    @JsonIgnore
    public MProperty getPropertyIncludeRelatedObjects() {
        return view.getApp().getObject().getPropertyIncludeRelatedObjects(propertyId);
    }
    
    /**
     * 或者本方对象属性，如果是关联对象属性则返回null
     * @return
     */
    @JsonIgnore
    public MProperty getProperty() {
        return view.getApp().getObject().getProperty(propertyId);
    }

    @JsonIgnore
    public MRelation getRelation() {
        return MObjectDto.getRelation(view.getApp().getObject(), relationId);
    }

    @JsonIgnore
    public MCrud getRelatedCrud () {
        String crudId = data.getString(PARAM_RELATED_CRUD);
        if (!WoKit.isEmpty(crudId)) {
            MApp app = WoKit.getBean(MAppMapper.class).selectById(crudId);
            MCrud crud = new MCrud(app, this.getView().getApp().getObject().getRequest());
            return crud;
        }
        MRelation r = this.getRelation();
        if (r == null) {
            throw new MException(MException.VIEWPROP_R_ERR, "表单", this.id);
        }
        if (r.is2C()) {
            throw new MException(MException.VIEWPROP_R_DENY, this.id);
        }
        MApp app = WoKit.getBean(MAppMapper.class).selectOne(new QueryWrapper<MApp>().eq("object_id", r.getRelatedObjectId()).eq("type", MAppDto.TYPE_CRUD).last("limit 1"));
        MCrud crud = new MCrud(app, this.getView().getApp().getObject().getRequest());
        return crud;
    }

    @JsonIgnore
    public List<MCrud> getRelatedCruds () {
    	List<MCrud> cruds = new ArrayList<MCrud>();
        String crudIds = data.getString(PARAM_RELATED_CRUD);
        if (!WoKit.isEmpty(crudIds)) {
        	for (String crudId : crudIds.split(",")) {
        		MApp app = WoKit.getBean(MAppMapper.class).selectById(crudId);
                MCrud crud = new MCrud(app, this.getView().getApp().getObject().getRequest());
                cruds.add(crud);
        	}
            return cruds;
        }
        MRelation r = this.getRelation();
        if (r == null) {
            throw new MException(MException.VIEWPROP_R_ERR, "表单", this.id);
        }
        for (String relatedObjectId : r.getRelatedObjectId().split(",")) {
        	MApp app = WoKit.getBean(MAppMapper.class).selectOne(new QueryWrapper<MApp>().eq("object_id", relatedObjectId).eq("type", MAppDto.TYPE_CRUD).last("limit 1"));
            MCrud crud = new MCrud(app, this.getView().getApp().getObject().getRequest());
            cruds.add(crud);
        }
        return cruds;
    }
    
    @JsonIgnore
    public Boolean isRelatedSelectorSingle () {
        // PARAM_RELATED_SINGLE
        if (data.getString(PARAM_RELATED_SINGLE) == null) {
            MRelation r = this.getRelation();
            if (r == null) {
            	return true;
            }
            return r.getType().endsWith("1");
        }
        if (data.getString(PARAM_RELATED_SINGLE).equals("false")) {
            return false;
        }
        return true;
    }

    /**
     * @return
     */
    @JsonIgnore
    public List<MProperty> getSearchProperties() {
        String propIds = getPropertyId();
        if (WoKit.isEmpty(propIds)) {
            throw new MException(MException.VIEWPROP_PROP_NULL, "查询", this.getId());
        }
        List<MProperty> props = new ArrayList<MProperty>();
        String[] ids = propIds.split(",");

        MRelation r = this.getRelation();
        for (String id : ids) {
            MProperty p = null;
            if (r != null) {
                p = MObjectDto.getProperty(r.getRelatedObject(), id);
            } else {
                p = MObjectDto.getProperty(this.getView().getApp().getObject(), id);
            }
            if (p == null) {
                throw new MException(MException.VIEWPROP_PROP_ERR, "查询", this.getId());
            }
            props.add(p);
        }
        return props;
    }

    /**
     * 获取where语句片段
     *
     * @param field
     * @param val
     * @param expression
     * @return
     */
    public static String getSqlCondition(String field, String val, String expression) {
        if (WoKit.isEmpty(val)) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("field", field);
        map.put("value", val);
        return WoKit.getBean(WoVelocityKit.class).parse(expression, map);
    }

    /**
     * 获取where语句片段，例如：(w_id = 'xxxx' or w_name = 'yyy')
     *
     * @param val
     * @return
     */
    public String getSqlCondition(String val) {
        if (WoKit.isEmpty(val)) {
            return null;
        }
        List<MProperty> props = this.getSearchProperties();
        MRelation r = this.getRelation();
        StringBuffer sc = new StringBuffer();
        sc.append("(");
        for (int i = 0; i < props.size(); i++) {
            MProperty p = props.get(i);
            String field = (r == null ? this.getView().getApp().getObject().getNo() : r.getId()) + "." + p.getName();
            // 多个属性之间是“或”的关系
            if (i > 0) {
                sc.append(" or ");
            }
            sc.append("(");
            String compareType = data.getString(PARAM_COMPARE);
            if (COMPARE_EQUAL.equals(compareType)) {
                String exp = "${field} = " + p.getSqlValue("${value}");
                sc.append(getSqlCondition(field, val, exp));
            } else if (COMPARE_LIKE.equals(compareType)) {
                String exp = "${field} like " + p.getSqlValue("%${value}%");
                sc.append(getSqlCondition(field, val, exp));
            } else if (COMPARE_EXPRESSION.equals(compareType)) {
                String exp = data.getString(PARAM_COMPARE_EXP);
                sc.append(getSqlCondition(field, val, exp));
            } else if (COMPARE_SELECT_EXPRESSION.equals(compareType)) {
                String exp = val;
                sc.append(getSqlCondition(field, val, exp));
            }
            sc.append(")");
        }
        sc.append(")");
        return sc.toString();
    }

    /**
     * 在UI中显示的值
     *
     * @return
     */
    @JsonIgnore
    public String getUIValue() {
        Object val = this.getValue();
        if (WoKit.isEmpty(val)) {
            if (TYPE_FILE.equals(this.getType()) || TYPE_IMAGE.equals(this.getType())) {
                return "0";
            }
            return "";
        }
        if (val instanceof Object[]) {
            return WoKit.toString((Object[]) val);
        }
        if (TYPE_DATETIME.equals(this.getType())) {
        	return val.toString().split("[.]")[0].replace('T', ' ');
        }
        if (TYPE_DATE.equals(this.getType())) {
        	return val.toString().split("[ |T]")[0];
        }
        return val.toString();
    }

    /**
     * @return
     */
    @JsonIgnore
    public String getUrl() {
        if (WoKit.isEmpty(this.getType())) {
            return data.getString(MObjectDto.PARAM_URL);
        }
        String root = data.getString(MObjectDto.PARAM_URL_ROOT);
        if (WoKit.isEmpty(root)) {
            return "meta/" + this.getView().getType() + "/props/" + this.getType();
        }
        return root + this.getType();
    }

    /**
     * 获取用户输入值（value）替换标志位，用于标识value在不同情况下是否替换为W_SUBMITVALUE。
     * 标志位二进制第一位表示value为空时替换；第二位表示value不为空时替换。例如：1二进制为01，则value为空时替换，
     * value不为空时不替换。
     *
     * @return
     */
    @JsonIgnore
    private int getReplaceSubmit() {
        return data.getInt(PARAM_REPLACE_SUBMIT, 0);
    }

    public void setReplaceSubmit (int replaceSubmit) {
        data.put(PARAM_REPLACE_SUBMIT, replaceSubmit);
    }

    /**
	     * 获取表单加载值（value）替换标志位，用于标识value在不同情况下是否替换为W_INITVALUE。
	    *标志位二进制第一位表示value为空时替换；第二位表示value不为空时替换。例如：1二进制为01，则value为空时替换，
     * value不为空时不替换。
     *
     * @return
     */
    @JsonIgnore
    private Integer getReplaceInit() {
        return data.getInt(PARAM_REPLACE_INIT, 0);
    }

    public void setReplaceInit(int replaceLoad) {
        data.put(PARAM_REPLACE_INIT, replaceLoad);
    }
    /**
     * 表单加载值val是否替换为W_INITVALUE值
     *
     * @param val
     * @return
     */
    public boolean isReplaceInit(Object val) {
        if (WoKit.isEmpty(val) && (getReplaceInit() & REPLACE_EMPTY) == REPLACE_EMPTY) {
            return true;
        }
        if (!WoKit.isEmpty(val) && (getReplaceInit() & REPLACE_VALUE) == REPLACE_VALUE) {
            return true;
        }
        return false;
    }

    /**
     * 用户输入值val是否替换为W_SUBMITVALUE值
     *
     * @param val
     * @return
     */
    public boolean isReplaceSubmit(Object val) {
        if (WoKit.isEmpty(val) && (getReplaceSubmit() & REPLACE_EMPTY) == REPLACE_EMPTY) {
            return true;
        }
        if (!WoKit.isEmpty(val) && (getReplaceSubmit() & REPLACE_VALUE) == REPLACE_VALUE) {
            return true;
        }
        return false;
    }

    /**
     * @return
     */
    @JsonIgnore
    public String getSelectorHiddenName () {
        return this.id + SUFFIX_SELECTORHIDDEN;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Integer getIndex() {
        return index;
    }

    public void setIndex(Integer index) {
        this.index = index;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getPropertyId() {
        return propertyId;
    }

    public void setPropertyId(String propertyId) {
        this.propertyId = propertyId;
    }

    public String getRelationId() {
        return relationId;
    }

    public void setRelationId(String relationId) {
        this.relationId = relationId;
    }

    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public String getInitValue() {
        return initValue;
    }

    public void setInitValue(String initValue) {
        this.initValue = initValue;
    }

    public String getSubmitValue() {
        return submitValue;
    }

    public void setSubmitValue(String submitValue) {
        this.submitValue = submitValue;
    }

    public Integer getSubmit() {
        return submit;
    }

    public void setSubmit(Integer submit) {
        this.submit = submit;
    }

    public Integer getRowSpan() {
        return rowSpan;
    }

    public void setRowSpan(Integer rowSpan) {
        this.rowSpan = rowSpan;
    }

    public Integer getColSpan() {
        return colSpan;
    }

    public void setColSpan(Integer colSpan) {
        this.colSpan = colSpan;
    }

    public String getMin() {
        return min;
    }

    public void setMin(String min) {
        this.min = min;
    }

    public String getMax() {
        return max;
    }

    public void setMax(String max) {
        this.max = max;
    }

    public Integer getAllowsBlank() {
        return allowsBlank;
    }

    public void setAllowsBlank(Integer allowsBlank) {
        this.allowsBlank = allowsBlank;
    }

    public Integer getUnique() {
        return unique;
    }

    public void setUnique(Integer unique) {
        this.unique = unique;
    }

    public Integer getReadOnly() {
        return readonly;
    }

    public void setReadOnly(Integer readonly) {
        this.readonly = readonly;
    }

    @JsonIgnore
    public Boolean isReadonly () {
        if (this.view.getReadonly() == 1) {
            return true;
        }
        return Integer.valueOf(1).equals(getReadOnly());
    }
    
    public void setAjax (String value) {
    	data.bigPut(PARAM_AJAX, value);
    }
    
    @JsonIgnore
    public String getAjax () {
    	return data.getString(PARAM_AJAX);
    }
    
    public void setAjaxSql (String value) {
    	data.bigPut(PARAM_AJAX_SQL, value);
    }
    
    @JsonIgnore
    public String getAjaxSql () {
    	return data.getString(PARAM_AJAX_SQL);
    }
    
    public BigMap<String, Object> getData() {
        return data;
    }

    public void setData(BigMap<String, Object> data) {
        this.data = data;
    }

    @JsonIgnore
    public MViewDto getView() {
        return view;
    }

    public void setView(MViewDto view) {
        this.view = view;
    }

    @JsonIgnore
    public Boolean getMetaShow () {
        return data.getBoolean(MObjectDto.PARAM_META_SHOW, false);
    }

    public void setMetaShow (Boolean metaShow) {
        data.put(MObjectDto.PARAM_META_SHOW, metaShow);
    }
    
    /**
     * 仅适用于：TYPE_CHECK, TYPE_RADIO, TYPE_COMBO
     * @return
     */
    @JsonIgnore
    public String getDictionaryValues () {
    	String values = this.getUIValue();
    	if ("".equals(values) && Arrays.asList(TYPE_CHECK, TYPE_RADIO, TYPE_COMBO).contains(type)) {
    		if (allowsBlank == 0) {
    			values = "-1";
    		}
    	}
    	return values;
    }

    /**
     * form/search视图使用
     * @return
     */
    @JsonIgnore
    public String getDictionaryType () {
        return data.getString(PARAM_DICTIONARY);
    }

    public void setDictionaryType (String dictionaryType) {
        data.put(PARAM_DICTIONARY, dictionaryType);
    }
    
    /**
     * search视图使用
     * @return
     */
    @JsonIgnore
    public String getCompareType () {
        return data.getString(PARAM_COMPARE);
    }

    public void setCompareType (String compareType) {
        data.put(PARAM_COMPARE, compareType);
    }
    
    /**
     * search视图使用
     * @return
     */
    @JsonIgnore
    public String getCompareExpression () {
        return data.getString(PARAM_COMPARE_EXP);
    }

    public void setCompareExpression (String compareExpression) {
        data.put(PARAM_COMPARE_EXP, compareExpression);
    }
    
    @Override
    public int compareTo(MViewProperty o) {
        return this.getIndex() - o.getIndex();
    }
    
    /**
     * @return objectInputor等控件查询数据url
     */
    @JsonIgnore
    public String getSearchUrl () {
    	return data.getString(PARAM_SEARCH_URL);
    }
    
    /**
     * @param url
     */
    public void setSearchUrl (String url) {
    	data.put(PARAM_SEARCH_URL, url);
    }
    
    @JsonIgnore
    public String getDataUrl () {
    	return data.getString(PARAM_DATA_URL);
    }
    
    /**
     * @param url
     */
    public void setDataUrl (String url) {
    	data.put(PARAM_DATA_URL, url);
    }
    
    @JsonIgnore
    public String getListFilter () {
    	return data.getString(PARAM_LIST_FILTER);
    }
    
    /**
     * @param listFilter
     */
    public void setListFilter (String listFilter) {
    	data.put(PARAM_LIST_FILTER, listFilter);
    }
    
    @JsonIgnore
    public String getExpression () {
    	return data.getString(PARAM_EXPRESSION);
    }
    
    /**
     * @param ex
     */
    public void setExpression (String ex) {
    	data.put(PARAM_EXPRESSION, ex);
    }

    @JsonIgnore
    public String getListorJson () {
        if (data.containsKey(PARAM_LISTOR_FIELD)) {
            String values = getView().getUIKeyValues();
            if (data.containsKey(PARAM_LISTOR_SUFFIX)) {
                values = getView().getPropertyBySuffix(data.getString(PARAM_LISTOR_SUFFIX)).getUIValue();
            }
            return WoJsonKit.writeAsString(new BigMap<String, Object>().bigPut(data.getString(PARAM_LISTOR_FIELD), values));
        }
        return null;
    }
}
